package cn.skyquant.quant4j.service.boot.model.ylzc;

import cn.skyquant.quant4j.api.dto.ResultDTO;
import cn.skyquant.quant4j.api.ylzc.YlzcDTO;
import cn.skyquant.quant4j.api.ylzc.YlzcMap;
import cn.skyquant.quant4j.api.ylzc.YlzcService;
import cn.skyquant.quant4j.sdk.enums.Status;
import cn.skyquant.quant4j.sdk.enums.YlzcType;
import cn.skyquant.quant4j.sdk.util.bean.BeanTools;
import cn.skyquant.quant4j.service.boot.model.goods.Goods;
import cn.skyquant.quant4j.service.boot.model.goods.GoodsRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service("YlzcServiceImpl")
public class YlzcServiceImpl implements YlzcService {
    @Autowired
    YlzcRepository ylzcRepository;

    @Autowired
    GoodsRepository goodsRepository;

    private static final Sort sortThedate = new Sort(Sort.Direction.DESC,"thedate");
    ResultDTO<Void> error = ResultDTO.error("没有这个交易品种");

    @Transactional
    @Override
    public ResultDTO<Void> insert(String symbol, Integer period, Date thedate, YlzcType type, int level, double value) {
        if (symbol == null || type == null || thedate == null || value == 0 || level == 0) {
            return ResultDTO.error1;
        }
        List<Goods> goodsList = goodsRepository.findBySymbol(symbol);
        if(CollectionUtils.isEmpty(goodsList)){
            return error;
        }
        Ylzc ylzc = new Ylzc(symbol, period, thedate, type, level, value,Status.A);
        Ylzc db = ylzcRepository.save(ylzc);
        if(db.id!=null){
            return ResultDTO.success;
        }else {
            return ResultDTO.error;
        }
    }

    @Override
    public ResultDTO<YlzcDTO> get(Integer id) {
        if (id == null || id.intValue() == 0) {
            return ResultDTO.error1;
        }
        Optional<Ylzc> ylzcOptional = ylzcRepository.findById(id);
        if (ylzcOptional.isPresent()) {
            Ylzc ylzc = ylzcOptional.get();
            YlzcDTO ylzcDTO =  convertYlzcDoToDto(ylzc);
            return ResultDTO.success(ylzcDTO);
        }else {
            return ResultDTO.error2;
        }
    }

    @Transactional
    @Override
    public ResultDTO<Void> active(Integer id) {
        Optional<Ylzc> ylzcOptional = ylzcRepository.findById(id);
        if (ylzcOptional.isPresent()) {
            Ylzc ylzc = ylzcOptional.get();
            if(ylzc.status!=Status.A){
                ylzc.status = Status.A;
            }
            return ResultDTO.success;
        }else {
            return ResultDTO.error2;
        }
    }

    @Transactional
    @Override
    public ResultDTO<Void> disable(Integer id) {
        Optional<Ylzc> ylzcOptional = ylzcRepository.findById(id);
        if (ylzcOptional.isPresent()) {
            Ylzc ylzc = ylzcOptional.get();
            if(ylzc.status!=Status.S){
                ylzc.status = Status.S;
            }
            return ResultDTO.success;
        }else {
            return ResultDTO.error2;
        }
    }

    @Transactional
    @Override
    public ResultDTO<Void> update(Integer id, int newLevel, double newValue) {
        Optional<Ylzc> ylzcOptional = ylzcRepository.findById(id);
        if (ylzcOptional.isPresent()) {
            Ylzc ylzc = ylzcOptional.get();
            ylzc.level = newLevel;
            ylzc.value = newValue;
            return ResultDTO.success;
        }else {
            return ResultDTO.error2;
        }
    }

    @Override
    public ResultDTO<YlzcMap> query(String symbol, Integer period, Date beginTime, Date endTime) {
        List<Ylzc> ylzcList = ylzcRepository.findBySymbolAndTime(symbol,period,Status.A,beginTime,endTime,sortThedate);
        YlzcMap ylzcMap = new YlzcMap();
        for(Ylzc ylzc:ylzcList){
            if(ylzc.type==YlzcType.Y){
                ylzcMap.addYlw(convertYlzcDoToDto(ylzc));
            }else{
                ylzcMap.addZcw(convertYlzcDoToDto(ylzc));
            }
        }
        return ResultDTO.success(ylzcMap);
    }


    private static final YlzcDTO convertYlzcDoToDto(Ylzc ylzc){
        YlzcDTO ylzcDTO = new YlzcDTO();
        BeanTools.copyPublicFields(ylzc,ylzcDTO);
        return ylzcDTO;
    }

    private static final List<YlzcDTO> convertYlzcDosToDtos(List<Ylzc> list){
        return list.stream().map(x->convertYlzcDoToDto(x)).collect(Collectors.toList());
    }

    private static final Ylzc convertYlzcDtoToDo(YlzcDTO ylzc){
        Ylzc ylzcDTO = new Ylzc();
        BeanTools.copyPublicFields(ylzc,ylzcDTO);
        return ylzcDTO;
    }

    private static final List<Ylzc> convertYlzcDtosToDos(List<YlzcDTO> list){
        return list.stream().map(x->convertYlzcDtoToDo(x)).collect(Collectors.toList());
    }
}
